/****

    activequant - activestocks.eu

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

	
	contact  : contact@activestocks.eu
    homepage : http://www.activestocks.eu

****/
package org.activequant.util.spring;

import java.beans.PropertyEditorSupport;
import java.util.ArrayList;
import java.util.List;
import java.util.TimeZone;

import org.activequant.core.types.TimeStamp;
import org.activequant.core.util.TimeStampFormat;

/**
 * Spring helper to conveniently instantiate TimeStamp from a date/time string.
 * Allows specifying list of alternative formats. Editor will try to use the base format
 * for parsing. If this fails, it will try the list of alternatives in the order
 * they were specified. If alternative format matches, the resulting parsed value
 * is returned. If none of the formats matches, an exception will be thrown.<br/>
 * TimeStampPropertyEditor extends PropertyEditorSupport. Holds the following associated variables:
 * <ul>
 * <li>zone(String)</li>
 * <li>format(TimeStampFormat)</li>
 * <li>altFormats(List&lt;TimeStampFormat&gt;)</li>
 * </ul>
 * <b>History:</b><br>
 *  - [03.12.2007] Created (Mike Kroutikov)<br>
 *
 *  @author Mike Kroutikov
 */
public class TimeStampPropertyEditor extends PropertyEditorSupport {
	/**
	 * private final String DEFAULT_ZONE = "UTC";
	 */
	private final String DEFAULT_ZONE = "UTC";
	/**
	 * private final String DEFAULT_FORMAT = "yyyy/MM/dd HH:mm:ss.SSSnnnnnn";
	 */
	private final String DEFAULT_FORMAT = "yyyy/MM/dd HH:mm:ss.SSSnnnnnn";
	/**
	 * private String zone = DEFAULT_ZONE ("UTC")
	 */
	private String zone = DEFAULT_ZONE;
	/**
	 * private TimeStampFormat format = new TimeStampFormat(DEFAULT_FORMAT);
	 */
	private TimeStampFormat format = new TimeStampFormat(DEFAULT_FORMAT);
	/**
	 * private List&lt;TimeStampFormat&gt; altFormats = new ArrayList&lt;TimeStampFormat&gt;();
	 */
	private List<TimeStampFormat> altFormats = new ArrayList<TimeStampFormat>();
	/**
	 * returns <code>format.toString()</code> using the associated format(TimeStampFormat)
	 * @return
	 */
	public String getFormat() {
		return format.toString();
	}
	/**
	 * Sets the associated format(TimeStampFormat) with a new TimeStampFormat using the given val(String) as its format(String) and a default Locale.<br/>
	 * It also sets the TimeZone of the associated format(TimeStampFormat) with a TimeZone instance for the associated zone(String) (by default DEFAULT_ZONE ("UTC"))
	 * @param val
	 */
	public void setFormat(String val) {
		format = new TimeStampFormat(val);
		format.setTimeZone(TimeZone.getTimeZone(zone));
	}
	/**
	 * returns the associated zone(String) (by default DEFAULT_ZONE("UTC"))
	 * @return
	 */
	public String getTimeZone() {
		return zone;
	}
	/**
	 * Sets the associated zone(String) with the given val(String)<br/>
	 * Sets the TimeZone of the associated format(TimeStampFormat) with a TimeZone instance for the given val(String)
	 * @param val
	 */
	public void setTimeZone(String val) {
		zone = val;
		format.setTimeZone(TimeZone.getTimeZone(zone));
	}
	/**
	 * <strong>1.</strong> Clears the associated altFormats(List&lt;TimeStampFormat&gt;)<br/>
	 * <strong>2.</strong> Iterates the given formats(List&lt;String&gt;) and for each format(String) it creates and adds a TimeStampFormat to the 
	 * associated altFormats(List&lt;TimeStampFormat&gt;). Each TimeStampFormat is set with a TimeZone instance for the associated zone(String).
	 * @param formats
	 */
	public void setAltFormats(List<String> formats) {
		altFormats.clear();
		for(String fmtString : formats) {
			TimeStampFormat fmt = new TimeStampFormat(fmtString);
			fmt.setTimeZone(TimeZone.getTimeZone(zone));
			altFormats.add(fmt);
		}
	}
	/**
	 * Returns a List&lt;String&gt; holding a String representation for each of the associated altFormats(List&lt;TimeStampFormat&gt;)
	 * @return
	 */
	public List<String> getAltFormats() {
		List<String> out = new ArrayList<String>();
		for(TimeStampFormat fmt : altFormats) {
			out.add(fmt.toString());
		}
		return out;
	}
	/**
	 * <strong>1.</strong> Parses a timeStamp(TimeStamp) from the given text(String) using the associated format(TimeStampFormat) 
	 * (or any of the associated altFormats(List&lt;TimeStampFormat&gt;) if that doesn't work)<br/>
	 * <strong>2.</strong> Sets the inherited value(Object) of this TimeStampPropertyEditor with that timeStamp(TimeStamp)
	 */
	public void setAsText(String text) {
		
        setValue(parse(text));
    }
	/**
	 * Tries to parse and return a TimeStamp from the given text(String) using the associated format(TimeStampFormat).<br/>
	 * If that fails, it keeps trying with each of the associated altFormats(List&lt;TimeStampFormat&gt;) till it finds the right one.
	 * @param text
	 * @return
	 */
	private TimeStamp parse(String text) {
		try {
			return format.parse(text);
		} catch(Exception ex) {
//			ex.printStackTrace();
		}		
		for(TimeStampFormat altFmt : altFormats) {
			try {
				return altFmt.parse(text);
			} catch(Exception ex) {
//				ex.printStackTrace();
			}
		}
		throw new IllegalArgumentException("failed to parse time stamp value [" + text + "] using format: " + getFormat() + " and alternative formats: " + getAltFormats());
	}
}